<template>
    <div class="image_zoom" ref="magnifier" @mousemove="onMove" @mouseout="onLeave" @mouseover="onEnter" @click.capture="onPreview">
        <div class="image" :style="imageStyle">
            <img :src="imageUrl" alt="ImageZoom" @load="imgLoad">
        </div>
        <img :src="imageUrl" alt="" class="origin_size" :style="originStyle" v-show="zoomer">
    </div>
</template>

<script lang="ts">
    import { Vue, Component, Watch } from 'vue-property-decorator';

    @Component({
        props: {
            mode: {
                type: String,
                default: 'zoomer' // preview
            },
            image: {
                type: String,
                required: true
            },
            imageFull: {
                type: String,
                default: ''
            },
            width: {
                type: Number,
                default: 200
            },
            height: {
                type: Number,
                default: 200
            }
        }
    })
    export default class ImageZoom extends Vue {
        // 元素绝对位置
        // elPos = [0, 0];
        // 原图大小
        imageSize = [0, 0];
        // 视野位置
        viewPos = [0, 0];
        // 缩放比例
        scale = [0, 0];

        zoomer = false;

        get imageStyle() {
            return {
                width: this.width + 'px',
                height: this.height + 'px'
            }
        }

        get originStyle() {
            return {
                left: -this.viewPos[0] + 'px',
                top: -this.viewPos[1] + 'px'
            }
        }

        /**
         * 添加时间戳
         */
        get imageUrl() {
            return this.addTimestamp(this.image)
        }

        onEnter(e) {
            if (this.mode === 'preview') {
                return false;
            }
            this.zoomer = true;
            // 防止 resize 后导致位置变化
            // this.elPos[0] = this.$el.getBoundingClientRect().left+document.documentElement.scrollLeft;
            // this.elPos[1] = this.$el.getBoundingClientRect().top+document.documentElement.scrollTop;

            this.viewSize = [ this.$refs.magnifier.clientWidth, this.$refs.magnifier.clientHeight ];
            this.scale = [ this.viewSize[0] / this.imageSize[0], this.viewSize[1] / this.imageSize[1] ]
        }
        onMove(e) {
            if (this.mode === 'preview') {
                return false;
            }
            // 鼠标指针的相对当前事件源的相对位置
            // let relativePos = [
            //     e.pageX - this.elPos[0], 
            //     e.pageY - this.elPos[1]
            // ];
            let relativePos = this.mouseRelativePos(e.clientX, e.clientY);
            let zoomerLeft = relativePos[0] / this.scale[0]
            let zoomerTop = relativePos[1] / this.scale[1]
            if (this.imageSize[0] - zoomerLeft < this.viewSize[0]) {
                this.$set(this.viewPos, 0, this.imageSize[0] - this.viewSize[0]);
            } else {
                this.$set(this.viewPos, 0, zoomerLeft);
            }

            if (this.imageSize[1] - zoomerTop < this.viewSize[1]) {
                this.$set(this.viewPos, 1,  this.imageSize[1] - this.viewSize[1]);
            } else {
                this.$set(this.viewPos, 1, zoomerTop);
            }
        }

        onLeave(e) {
            this.zoomer = false;
            this.$set(this.viewPos, 0, 0);
            this.$set(this.viewPos, 1, 0);
        }

        onPreview(e) {
            if (this.mode !== 'preview') {
                return false;
            }
            this.$alert('<img src='+this.image+'>', {
                dangerouslyUseHTMLString: true,
                customClass: 'el-message-box-preview',
                showConfirmButton: false,
                closeOnClickModal: true,
                closeOnPressEscape: true,
                showClose: false,
                lockScroll: false
            });
        }

        imgLoad(e) {
            this.imageSize = [ e.target.naturalWidth, e.target.naturalHeight ];
        }

        mouseRelativePos(x, y) {
            let bbox = this.$el.getBoundingClientRect();
            return [
                (x - bbox.left),
                (y - bbox.top)
            ]
        }


        /**
         * 主要为图片 URL 添加时间戳参数
         * @param URL string
         */
        addTimestamp(URL:string):string {
            if (/\?/.test(URL)) {
                URL += `&${Date.now()}`
            } else {
                URL += `?${Date.now()}`
            }
            return URL;
        }

        mounted() {
            // 获取当前元素在页面的相对位置
            // this.elPos = [
            //     this.$el.getBoundingClientRect().left+document.documentElement.scrollLeft,
            //     this.$el.getBoundingClientRect().top+document.documentElement.scrollTop
            // ]
        }
    }
</script>

<style lang="scss">
    .image_zoom {
        display: inline-block;
        position: relative;
        box-sizing: border-box;
        cursor: zoom-in;
        overflow: hidden;
        .image {
            width: 400px;
            height: 400px;
            img {
                width: inherit;
                height: inherit;
            }
        }

        .origin_size {
            position: absolute;
        }
    }

    .el-message-box-preview {
        width: auto!important;
    }
</style>